/* 
lane 车道 优先级
alternate 备用
Phase 阶段
queue 队列
enqueue 入队
schedule 日程 调度
*/

/* 
在 React 的源码中，开始进行 diff 过程的方法是调用 reconcileChildren 函数
*/

// 函数 dispatchSetState 用于处理 setState 更新。
function dispatchSetState(fiber, queue, action) {
    // 检查是否有第二个回调参数。
    // 如果存在，则抛出错误，因为 setState 更新不支持第二个回调参数。
    if (typeof arguments[3] === 'function') {
        error("State updates from the useState() and useReducer() Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect().");
    }
    // 请求一个更新车道（lane），用于标识更新优先级。
    var lane = requestUpdateLane(fiber);
    var update = {
        // 更新车道
        lane: lane,
        // 更新动作
        action: action,
        // 是否有预先计算的状态
        hasEagerState: false,
        // 预先计算的状态
        eagerState: null,
        // 下一个更新
        next: null
    };
    // 如果当前处于渲染阶段，则将更新添加到渲染阶段的更新队列中。
    if (isRenderPhaseUpdate(fiber)) {
        enqueueRenderPhaseUpdate(queue, update);
    } else {
        // 获取当前 Fiber 的备份（alternate）
        var alternate = fiber.alternate;
        // 如果当前 Fiber 的车道是 NoLanes，且备份 Fiber 的车道也是 NoLanes，
        // 则说明更新队列目前是空的，我们可以预先计算下一个状态。
        if (fiber.lanes === NoLanes && (alternate === null || alternate.lanes === NoLanes)) {
            // 获取上次渲染的 Reducer 函数
            var lastRenderedReducer = queue.lastRenderedReducer;
            // 如果上次渲染的 Reducer 函数存在，则尝试预先计算下一个状态
            if (lastRenderedReducer !== null) {
                var prevDispatcher;
                // 切换到错误的 Dispatcher，以避免在 setState 更新中使用 Hooks
                {
                    prevDispatcher = ReactCurrentDispatcher$1.current;
                    ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
                }
                try {
                    // 获取上次渲染的状态
                    var currentState = queue.lastRenderedState;
                    // 使用 Reducer 函数预先计算下一个状态
                    var eagerState = lastRenderedReducer(currentState, action);
                    // 将预先计算的状态和使用的 Reducer 函数存储在更新对象中
                    update.hasEagerState = true;
                    update.eagerState = eagerState;
                    // 如果预先计算的状态与上次渲染的状态相同，则快速路径
                    // 我们可以完全跳过调度 React 重新渲染。
                    if (objectIs(eagerState, currentState)) {
                        // 快速路径。我们可以跳过调度 React 重新渲染。
                        // 仍然可能需要稍后重新调整这个更新，如果组件因为其他原因重新渲染，
                        // 并且那时 Reducer 函数已经改变。
                        enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update, lane);
                        return;
                    }
                } catch (error) {// 抑制错误。在渲染阶段会再次抛出。
                } finally {
                    // 切换回正确的 Dispatcher
                    {
                        ReactCurrentDispatcher$1.current = prevDispatcher;
                    }
                }
            }
        }
        // 将更新添加到并发阶段的更新队列中。
        var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
        // 如果 root 不是 null，则调度更新。
        if (root !== null) {
            // requestEventTime 是一个用于获取当前事件时间的函数。这个函数在 React 的协调（Reconciliation）过程中用于记录更新和操作的时间戳。
            // 时间戳可以帮助 React 确定更新和操作的顺序，以及它们的优先级。
            var eventTime = requestEventTime();
            // scheduleUpdateOnFiber 函数用于调度一个更新任务，这个更新任务会被添加到 React 的更新队列中，并在适当的时机执行。
            // 这个函数是 React 协调（Reconciliation）过程中的一个关键部分，它帮助 React 管理更新队列并决定何时执行更新。
            scheduleUpdateOnFiber(root, fiber, lane, eventTime);
            // 函数用于将一个更新与一个或多个过渡（transition）关联起来。
            // 这个函数是 React 协调（Reconciliation）过程中的一个组成部分，用于处理组件的状态更新和过渡效果
            entangleTransitionUpdate(root, queue, lane);
        }
    }
}   


// 函数 scheduleUpdateOnFiber 用于调度一个更新任务。
function scheduleUpdateOnFiber(root, fiber, lane, eventTime) {
    // 检查是否有嵌套的更新。
    checkForNestedUpdates();
  
    // 检查是否在插入效果（insertion effect）中执行。
    {
      if (isRunningInsertionEffect) {
        error('useInsertionEffect must not schedule updates.');
      }
    }
  
    // 检查是否在执行被动效果（passive effects）的刷新中。
    {
      if (isFlushingPassiveEffects) {
        didScheduleUpdateDuringPassiveEffects = true;
      }
    } // 标记根（root）有一个待处理的更新。
  
    markRootUpdated(root, lane, eventTime);
  
    // 如果当前执行上下文包含渲染上下文（Render Context），并且根（root）是工作中的根（workInProgressRoot），
    // 则这是一个在渲染阶段触发的更新。这通常是一个错误，除非更新来自用户空间（例如，local hook updates），
    // 这些更新会以不同的方式处理，并且不会到达这个函数。
    if ((executionContext & RenderContext) !== NoLanes && root === workInProgressRoot) {
      warnAboutRenderPhaseUpdatesInDEV(fiber); // 跟踪在渲染阶段更新的车道
    } else {
      // 这是一个正常的更新，调度来自渲染阶段之外。例如，在输入事件期间。
      {
        if (isDevToolsPresent) {
          addFiberToLanesMap(root, fiber, lane);
        }
      }
  
      warnIfUpdatesNotWrappedWithActDEV(fiber);
  
      if (root === workInProgressRoot) {
        // 接收了对正在渲染的树的更新。标记在这个根上有一个中间的更新工作。
        // 除非 `deferRenderPhaseUpdateToNextBatch` 标志关闭并且这是一个渲染阶段的更新。
        // 在这种情况下，我们不将渲染阶段的更新视为中间更新，以保持向后兼容性。
        if ( (executionContext & RenderContext) === NoContext) {
          workInProgressRootInterleavedUpdatedLanes = mergeLanes(workInProgressRootInterleavedUpdatedLanes, lane);
        }
  
        if (workInProgressRootExitStatus === RootSuspendedWithDelay) {
          // 根已经延迟挂起，这意味着渲染肯定不会完成。由于我们有一个新的更新，让我们现在标记为挂起，
          // 标记传入的更新之前。这具有中断当前渲染并切换到更新的效果。
          // TODO: 确保这不会覆盖我们在已经开始渲染时发生的ping。
          markRootSuspended$1(root, workInProgressRootRenderLanes);
        }
      }
  
      ensureRootIsScheduled(root, eventTime);
  
      // 如果车道是 SyncLane 并且执行上下文是 NoContext 并且模式中不包含并发模式（Concurrent Mode），
      // 并且不是在 legacy 模式下批处理更新（isBatchingLegacy），则立即刷新同步工作，除非我们已经在工作或者在批处理中。
      // 这样做的目的是为了保持 legacy 模式下的历史行为。
      if (lane === SyncLane && executionContext === NoContext && (fiber.mode & ConcurrentMode) === NoMode && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode.
      !( ReactCurrentActQueue$1.isBatchingLegacy)) {
        resetRenderTimer();
        flushSyncCallbacksOnlyInLegacyMode();
      }
    }
  }
// 函数 entangleTransitionUpdate 用于将一个更新与一个或多个过渡（transition）关联起来。
function entangleTransitionUpdate(root, queue, lane) {
    // 如果车道（lane）与过渡（transition）相关联，则执行以下操作。
    if (isTransitionLane(lane)) {
      // 获取更新队列（queue）的车道（lanes）。
      var queueLanes = queue.lanes;
  
      // 如果更新队列中的任何与过渡相关的车道（entangled lanes）在根（root）上不再待处理，
      // 则它们必须已经完成。我们可以从共享队列中移除它们，这个队列代表实际待处理的 lanes 的超集。
      // 在某些情况下，我们可能会关联比实际需要的更多的车道，但这是可以的。
      // 实际上，如果我们在应该关联时没有关联，那会更糟。
      queueLanes = intersectLanes(queueLanes, root.pendingLanes);
  
      // 将新的过渡车道与其它过渡车道关联起来。
      var newQueueLanes = mergeLanes(queueLanes, lane);
      queue.lanes = newQueueLanes; // 即使更新队列（queue.lanes）已经包含车道（lane），我们也无法确定
      // 车道（lane）是否已经完成，因为我们最后一次关联它时它还没有完成。
      // 所以我们需要再次关联它，以确保万无一失。
  
      // 标记根（root）与新的队列车道（newQueueLanes）关联。
      markRootEntangled(root, newQueueLanes);
    }
  }
    